// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/http/failing_http_transaction_factory.h"

#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "net/base/load_timing_info.h"
#include "net/base/upload_progress.h"
#include "net/http/http_response_info.h"
#include "net/socket/connection_attempts.h"

namespace net {

class AuthCredentials;
class BoundNetLog;
class HttpRequestHeaders;
class IOBuffer;
class X509Certificate;

namespace {

// A simple class to interpose between the cache and network http layers.
// These transactions can be generated by the FailingHttpTransactionFactory
// to test interactions between cache and network.
class FailingHttpTransaction : public HttpTransaction {
 public:
  explicit FailingHttpTransaction(Error error);
  ~FailingHttpTransaction() override;

  // HttpTransaction
  int Start(const HttpRequestInfo* request_info,
            const CompletionCallback& callback,
            const BoundNetLog& net_log) override;
  int RestartIgnoringLastError(const CompletionCallback& callback) override;
  int RestartWithCertificate(X509Certificate* client_cert,
                             const CompletionCallback& callback) override;
  int RestartWithAuth(const AuthCredentials& credentials,
                      const CompletionCallback& callback) override;
  bool IsReadyToRestartForAuth() override;
  int Read(IOBuffer* buf,
           int buf_len,
           const CompletionCallback& callback) override;
  void StopCaching() override;
  bool GetFullRequestHeaders(HttpRequestHeaders* headers) const override;
  int64 GetTotalReceivedBytes() const override;
  void DoneReading() override;
  const HttpResponseInfo* GetResponseInfo() const override;
  LoadState GetLoadState() const override;
  UploadProgress GetUploadProgress() const override;
  void SetQuicServerInfo(QuicServerInfo* quic_server_info) override;
  bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override;
  void SetPriority(RequestPriority priority) override;
  void SetWebSocketHandshakeStreamCreateHelper(
      WebSocketHandshakeStreamBase::CreateHelper* create_helper) override;
  void SetBeforeNetworkStartCallback(
      const BeforeNetworkStartCallback& callback) override;
  void SetBeforeProxyHeadersSentCallback(
      const BeforeProxyHeadersSentCallback& callback) override;
  int ResumeNetworkStart() override;
  void GetConnectionAttempts(ConnectionAttempts* out) const override;

 private:
  Error error_;
  HttpResponseInfo response_;
};

FailingHttpTransaction::FailingHttpTransaction(Error error) : error_(error) {
  DCHECK_LT(error, OK);
}

FailingHttpTransaction::~FailingHttpTransaction() {}

int FailingHttpTransaction::Start(const HttpRequestInfo* request_info,
                                  const CompletionCallback& callback,
                                  const BoundNetLog& net_log)  {
  base::MessageLoop::current()->PostTask(
      FROM_HERE, base::Bind(callback, error_));
  return ERR_IO_PENDING;
}

int FailingHttpTransaction::RestartIgnoringLastError(
    const CompletionCallback& callback)  {
  return ERR_FAILED;
}

int FailingHttpTransaction::RestartWithCertificate(
    X509Certificate* client_cert,
    const CompletionCallback& callback)  {
  return ERR_FAILED;
}

int FailingHttpTransaction::RestartWithAuth(
    const AuthCredentials& credentials,
    const CompletionCallback& callback)  {
  return ERR_FAILED;
}

bool FailingHttpTransaction::IsReadyToRestartForAuth()  {
  return false;
}

int FailingHttpTransaction::Read(IOBuffer* buf, int buf_len,
                                 const CompletionCallback& callback)  {
  NOTREACHED();
  return ERR_FAILED;
}

void FailingHttpTransaction::StopCaching()  {}

bool FailingHttpTransaction::GetFullRequestHeaders(
    HttpRequestHeaders* headers) const  {
  return false;
}

int64 FailingHttpTransaction::GetTotalReceivedBytes() const  {
  return 0;
}

void FailingHttpTransaction::DoneReading()  {
  NOTREACHED();
}

const HttpResponseInfo* FailingHttpTransaction::GetResponseInfo() const  {
  return &response_;
}

LoadState FailingHttpTransaction::GetLoadState() const  {
  return LOAD_STATE_IDLE;
}

UploadProgress FailingHttpTransaction::GetUploadProgress() const  {
  return UploadProgress();
}

void FailingHttpTransaction::SetQuicServerInfo(
    QuicServerInfo* quic_server_info) {
}

bool FailingHttpTransaction::GetLoadTimingInfo(
    LoadTimingInfo* load_timing_info) const  {
  return false;
}

void FailingHttpTransaction::SetPriority(RequestPriority priority)  {}

void FailingHttpTransaction::SetWebSocketHandshakeStreamCreateHelper(
    WebSocketHandshakeStreamBase::CreateHelper* create_helper)  {
  NOTREACHED();
}

void FailingHttpTransaction::SetBeforeNetworkStartCallback(
    const BeforeNetworkStartCallback& callback)  {
}

void FailingHttpTransaction::SetBeforeProxyHeadersSentCallback(
    const BeforeProxyHeadersSentCallback& callback)  {
}

int FailingHttpTransaction::ResumeNetworkStart()  {
  NOTREACHED();
  return ERR_FAILED;
}

void FailingHttpTransaction::GetConnectionAttempts(
    ConnectionAttempts* out) const {
  NOTIMPLEMENTED();
}

}  // namespace

FailingHttpTransactionFactory::FailingHttpTransactionFactory(
    HttpNetworkSession* session,
    Error error) : session_(session), error_(error) {
  DCHECK_LT(error, OK);
}

FailingHttpTransactionFactory::~FailingHttpTransactionFactory() {}

// HttpTransactionFactory:
int FailingHttpTransactionFactory::CreateTransaction(
    RequestPriority priority,
    scoped_ptr<HttpTransaction>* trans) {
  trans->reset(new FailingHttpTransaction(error_));
  return OK;
}

HttpCache* FailingHttpTransactionFactory::GetCache() {
  return NULL;
}

HttpNetworkSession* FailingHttpTransactionFactory::GetSession() {
  return session_;
}

}  // namespace net

